package com.jweb.framework.ws.soap.axiom;

import java.util.Locale;

import javax.xml.namespace.QName;


import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axiom.soap.SOAPProcessingException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.soap.axiom.AxiomSoapFaultException;
import org.springframework.ws.soap.axiom.support.AxiomUtils;
import org.springframework.ws.soap.soap11.Soap11Body;
import org.springframework.ws.soap.soap11.Soap11Fault;
import org.springframework.xml.namespace.QNameUtils;
/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：Axiom-specific version of <code>org.springframework.ws.soap.Soap11Body</code>.
 */
class AxiomSoap11Body extends AxiomSoapBody implements Soap11Body {
	
	private final boolean langAttributeOnSoap11FaultString  ;
	// axiomBody="<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"></soapenv:Body>"
	AxiomSoap11Body(SOAPBody axiomBody , SOAPFactory axiomFactory , boolean payloadCaching , boolean langAttributeOnSoap11FaultString){
		super(axiomBody, axiomFactory, payloadCaching);
		this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString ;
	}
	
	public Soap11Fault addMustUnderstandFault(String faultString , Locale locale) {
		SOAPFault fault = addStandardFault("MustUnderstand" , faultString , locale);
		return new AxiomSoap11Fault(fault , getAxiomFactory());
	}
	
	public Soap11Fault addClientOrSenderFault(String faultString , Locale locale){
		SOAPFault fault = addStandardFault("Client" , faultString , locale);
		return new AxiomSoap11Fault(fault , getAxiomFactory());
	}
	
	public Soap11Fault addServerOrReceiverFault(String faultString , Locale locale) {
		SOAPFault fault = addStandardFault("Server" , faultString , locale);
		return new AxiomSoap11Fault(fault , getAxiomFactory());
	}
	
	public Soap11Fault addVersionMismatchFault(String faultString , Locale locale) {
		SOAPFault fault = addStandardFault("VersionMismatch" , faultString , locale);
		return new AxiomSoap11Fault(fault , getAxiomFactory());
	}
	
	/*public Soap11Fault addFault(QName code , String faultString , Locale faultStringLocale) {
		Assert.notNull(code , "No faultCode given");
		Assert.hasLength(faultString , "faultString cannot be empty");
		if(!StringUtils.hasLength(code.getNamespaceURI())){
			throw new IllegalArgumentException("A fault code with namespace and local part must be specific for a custom fault code");
		}
		if(!langAttributeOnSoap11FaultString){
			faultStringLocale = null ;
		}
		try {
			AxiomUtils.removeContents(getAxiomBody());
			SOAPFault fault = getAxiomFactory().createSOAPFault(getAxiomBody());
			SOAPFaultCode faultCode = getAxiomFactory().createSOAPFaultCode(fault);
			setValueText(code , fault , faultCode);
			SOAPFaultReason faultReason = getAxiomFactory().createSOAPFaultReason(fault);
			if(faultReason != null){
				addLangAttribute(faultStringLocale , faultReason);
			}
			faultReason.setText(faultString);
			
			return new AxiomSoap11Fault(fault , getAxiomFactory());
		} catch (SOAPProcessingException e) {
			throw new AxiomSoapFaultException(e);
		}
		
	}*/
	
	 public Soap11Fault addFault(QName code, String faultString, Locale faultStringLocale) {
	        Assert.notNull(code, "No faultCode given");
	        Assert.hasLength(faultString, "faultString cannot be empty");
	        if (!StringUtils.hasLength(code.getNamespaceURI())) {
	            throw new IllegalArgumentException(
	                    "A fault code with namespace and local part must be specific for a custom fault code");
	        }
	        if (!langAttributeOnSoap11FaultString) {
	            faultStringLocale = null;
	        }
	        try {
	            AxiomUtils.removeContents(getAxiomBody());
	            SOAPFault fault = getAxiomFactory().createSOAPFault(getAxiomBody());
	            SOAPFaultCode faultCode = getAxiomFactory().createSOAPFaultCode(fault);
	            setValueText(code, fault, faultCode);
	            SOAPFaultReason faultReason = getAxiomFactory().createSOAPFaultReason(fault);
	            if (faultStringLocale != null) {
	                addLangAttribute(faultStringLocale, faultReason);
	            }
	            faultReason.setText(faultString);
	            return new AxiomSoap11Fault(fault, getAxiomFactory());

	        }
	        catch (SOAPProcessingException ex) {
	            throw new AxiomSoapFaultException(ex);
	        }
	    }
	
	private void setValueText(QName code , SOAPFault fault , SOAPFaultCode faultCode) {
		String prefix = QNameUtils.getPrefix(code);
		if(StringUtils.hasLength(code.getNamespaceURI()) && StringUtils.hasLength(prefix)){
			OMNamespace namespace = fault.findNamespaceURI(prefix);
			if(namespace == null){
				fault.declareNamespace(code.getNamespaceURI() , prefix);
			}
		}
		else if(StringUtils.hasLength(code.getNamespaceURI())){
			OMNamespace namespace = fault.findNamespace(code.getNamespaceURI(), null);
			if(namespace == null){
				namespace = fault.declareNamespace(code.getNamespaceURI(), "");
			}
			code = QNameUtils.createQName(code.getNamespaceURI(), code.getLocalPart(), namespace.getPrefix());
		}
		faultCode.setText(code);
	}
	
	
	private SOAPFault addStandardFault(String localName , String faultString , Locale locale) {
		Assert.notNull(faultString , "No faultString given");
		try {
			AxiomUtils.removeContents(getAxiomBody());
			SOAPFault fault = getAxiomFactory().createSOAPFault(getAxiomBody());
			SOAPFaultCode faultCode = getAxiomFactory().createSOAPFaultCode(fault);
			faultCode.setText(QNameUtils.createQName(fault.getNamespace().getNamespaceURI(), localName , fault.getNamespace().getPrefix()));
			SOAPFaultReason faultReason = getAxiomFactory().createSOAPFaultReason(fault); 
			if(locale != null){
				addLangAttribute(locale , faultReason);
			}
			faultReason.setText(faultString);
			return fault ;
		} catch (SOAPProcessingException e) {
			throw new AxiomSoapFaultException(e);
		}
	}
	
	private void addLangAttribute(Locale locale , SOAPFaultReason faultReason) {
		OMNamespace xmlNamespace = getAxiomFactory().createOMNamespace("http://www.w3.org/XML/1998/namespace", "xml");
		OMAttribute langAttribute = getAxiomFactory().createOMAttribute("lang", xmlNamespace , AxiomUtils.toLanguage(locale));
		faultReason.addAttribute(langAttribute);
	}
	
	public Soap11Fault getFault(){
		SOAPFault axiomFault = getAxiomBody().getFault();
		return axiomFault != null ? new AxiomSoap11Fault(axiomFault , getAxiomFactory()) : null ;
	}
	
	
	
}
